// Copyright (c) 2023 - 2025 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package identity implements the Identity monad, the simplest possible monad.

# Overview

The Identity monad is a trivial monad that simply wraps a value without adding
any computational context. It's the identity element in the category of monads,
meaning it doesn't add any effects or behavior - it just passes values through.

While seemingly useless, the Identity monad serves several important purposes:
  - As a baseline for understanding more complex monads
  - For testing monad transformers
  - As a default when no specific monad is needed
  - For generic code that works with any monad

In this implementation, Identity[A] is simply represented as type A itself,
making it a zero-cost abstraction.

# Core Concepts

The Identity monad implements the standard monadic operations:

  - Of: Wraps a value (identity function)
  - Map: Transforms the wrapped value
  - Chain (FlatMap): Chains computations
  - Ap: Applies a wrapped function to a wrapped value

Since Identity adds no context, all these operations reduce to simple function
application.

# Basic Usage

Creating and transforming Identity values:

	// Of wraps a value (but it's just the identity)
	x := identity.Of(42)
	// x is just 42

	// Map transforms the value
	doubled := identity.Map(func(n int) int {
	    return n * 2
	})(x)
	// doubled is 84

	// Chain for monadic composition
	result := identity.Chain(func(n int) int {
	    return n + 10
	})(doubled)
	// result is 94

# Functor Operations

Map transforms values:

	import F "github.com/IBM/fp-go/v2/function"

	// Simple mapping
	result := F.Pipe1(
	    5,
	    identity.Map(func(n int) int { return n * n }),
	)
	// result is 25

	// MapTo replaces with a constant
	result := F.Pipe1(
	    "ignored",
	    identity.MapTo[string, int](100),
	)
	// result is 100

# Applicative Operations

Ap applies wrapped functions:

	add := func(a int) func(int) int {
	    return func(b int) int {
	        return a + b
	    }
	}

	// Apply a curried function
	result := F.Pipe1(
	    add(10),
	    identity.Ap[int, int](5),
	)
	// result is 15

# Monad Operations

Chain for sequential composition:

	// Chain multiple operations
	result := F.Pipe2(
	    10,
	    identity.Chain(func(n int) int { return n * 2 }),
	    identity.Chain(func(n int) int { return n + 5 }),
	)
	// result is 25

	// ChainFirst executes for side effects but keeps original value
	result := F.Pipe1(
	    42,
	    identity.ChainFirst(func(n int) string {
	        return fmt.Sprintf("Value: %d", n)
	    }),
	)
	// result is still 42

# Do Notation

The package provides "do notation" for imperative-style composition:

	type Result struct {
	    X int
	    Y int
	    Sum int
	}

	result := F.Pipe3(
	    identity.Do(Result{}),
	    identity.Bind(
	        func(r Result) func(int) Result {
	            return func(x int) Result {
	                r.X = x
	                return r
	            }
	        },
	        func(Result) int { return 10 },
	    ),
	    identity.Bind(
	        func(r Result) func(int) Result {
	            return func(y int) Result {
	                r.Y = y
	                return r
	            }
	        },
	        func(Result) int { return 20 },
	    ),
	    identity.Let(
	        func(r Result) func(int) Result {
	            return func(sum int) Result {
	                r.Sum = sum
	                return r
	            }
	        },
	        func(r Result) int { return r.X + r.Y },
	    ),
	)
	// result is Result{X: 10, Y: 20, Sum: 30}

# Sequence and Traverse

Convert tuples of Identity values:

	import T "github.com/IBM/fp-go/v2/tuple"

	// Sequence a tuple
	tuple := T.MakeTuple2(1, 2)
	result := identity.SequenceTuple2(tuple)
	// result is T.Tuple2[int, int]{1, 2}

	// Traverse with transformation
	tuple := T.MakeTuple2(1, 2)
	result := identity.TraverseTuple2(
	    func(n int) int { return n * 2 },
	    func(n int) int { return n * 3 },
	)(tuple)
	// result is T.Tuple2[int, int]{2, 6}

# Monad Interface

Get a monad instance for generic code:

	m := identity.Monad[int, string]()

	// Use monad operations
	value := m.Of(42)
	mapped := m.Map(func(n int) string {
	    return fmt.Sprintf("Number: %d", n)
	})(value)

# Why Identity?

The Identity monad might seem pointless, but it's useful for:

1. Testing: Test monad transformers with a simple base monad
2. Defaults: Provide a default when no specific monad is needed
3. Learning: Understand monad laws without additional complexity
4. Abstraction: Write generic code that works with any monad

Example of generic code:

	func ProcessWithMonad[M any](
	    monad monad.Monad[int, string, M, M, func(int) M],
	    value int,
	) M {
	    return F.Pipe2(
	        monad.Of(value),
	        monad.Map(func(n int) int { return n * 2 }),
	        monad.Map(func(n int) string { return fmt.Sprintf("%d", n) }),
	    )
	}

	// Works with Identity
	result := ProcessWithMonad(identity.Monad[int, string](), 21)
	// result is "42"

# Type Alias

The package defines:

	type Operator[A, B any] = func(A) B

This represents an Identity computation from A to B, which is just a function.

# Functions

Core operations:
  - Of[A any](A) A - Wrap a value (identity)
  - Map[A, B any](func(A) B) func(A) B - Transform value
  - Chain[A, B any](func(A) B) func(A) B - Monadic bind
  - Ap[B, A any](A) func(func(A) B) B - Apply function

Monad variants:
  - MonadMap, MonadChain, MonadAp - Uncurried versions

Additional operations:
  - MapTo[A, B any](B) func(A) B - Replace with constant
  - ChainFirst[A, B any](func(A) B) func(A) A - Execute for effect
  - Flap[B, A any](A) func(func(A) B) B - Flip application

Do notation:
  - Do[S any](S) S - Initialize context
  - Bind[S1, S2, T any] - Bind computation result
  - Let[S1, S2, T any] - Bind pure value
  - LetTo[S1, S2, B any] - Bind constant
  - BindTo[S1, T any] - Initialize from value
  - ApS[S1, S2, T any] - Apply in context

Sequence/Traverse:
  - SequenceT1-10 - Sequence tuples of size 1-10
  - SequenceTuple1-10 - Sequence tuple types
  - TraverseTuple1-10 - Traverse with transformations

Monad instance:
  - Monad[A, B any]() - Get monad interface

# Related Packages

  - function: Function composition utilities
  - monad: Monad interface definition
  - tuple: Tuple types for sequence operations
*/
package identity

//go:generate go run .. identity --count 10 --filename gen.go
